/* Copyright (C) 2016 RDA Technologies Limited and/or its affiliates("RDA").
* All rights reserved.
*
* This software is supplied "AS IS" without any warranties.
* RDA assumes no responsibility or liability for the use of the software,
* conveys no license or title under any patent, copyright, or mask work
* right to the product. RDA reserves the right to make changes in the
* software without notification.  RDA also make no representation or
* warranty that such application will be suitable for the specified use
* without further testing or modification.
*/
#define OSI_LOG_TAG OSI_MAKE_LOG_TAG('q', 'x', 'w', 'z')

#include "qxwz_service.h"
#include "qxwz_sdk_hl.h"
#include "log_task.h"
#include "flash_buffer.h"
#include "flash_config.h"
#include "com_lib.h"

#define QXWZ_SDK_TEST ( 0 )

#if QXWZ_SDK_TEST

#define APPKEY 				"A48o1u8v2kid"   //服务中
#define APPSECRET 			"33e4834941f91e25"
#define DEVICE_ID           "20211213001"
#define DEVICE_TYPE         "MC120A_INSIDE_ODO"

#endif
#define QXWZ_DATA_RECV_MAX_LEN  ( 1024 * 2)
#define IOCTL_CMD_GPDRC_CFG     ( 107 )
#define IOCTL_CMD_GPDRC4_CFG    ( 106 )
#define GPDRC_MAX_LEN           ( 1024 )
QXWZSdkInterface *sdk_hl    = NULL;
QXWZSdkConfig cfg = {0};
qxwz_nmea_info_fun qxwz_nmea_info_cb = NULL;
qxwz_save_cfg_infor_t qxwz_save_cfg_infor = {0};
uint32_t qxwz_timer_handle;
uint32_t qxwz_timer_counter_reg;

static void qxwz_software_timer_function(void *arg);
static uint32_t qxwz_software_timer_start( void );
static void qxwz_software_timer_stop( void );
static qxwz_data_active_status_e qxwz_data_active_st;
static uint8_t qxwz_data_recv_buf[QXWZ_DATA_RECV_MAX_LEN];
static uint32_t qxwz_data_recv_len;

static QXWZSdkCallbacks cbs    =
{
    .size              = 0,
    .fill_raw_data     = NULL,
    .fill_nmea_info    = NULL,
    .status_response   = NULL,
};

static void fill_raw_data_cb(unsigned char *buf, unsigned int len)
{
    log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"fill_raw_data_cb %s,[%d]" ,buf,len );
}

static void fill_nmea_info_cb( QXGnssUtcTime time, const char *nmea, unsigned int len)
{
    if( qxwz_data_recv_len == 0 )
    {
        qxwz_data_active_st = DATA_ACTIVE_SUCC;     /*启动定时*/
    }
    if( qxwz_data_recv_len >= QXWZ_DATA_RECV_MAX_LEN )
    {
        qxwz_data_recv_len = 0;
    }
    memcpy( (uint8_t *)&qxwz_data_recv_buf[qxwz_data_recv_len], ( const char *)nmea, len );
    qxwz_data_recv_len += len;
    qxwz_timer_counter_reg = 0;                     /*刷新定时器时钟*/
}

static void status_response_cb(QXWZSdkStatus status)
{
    log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"status_response_cb [%d]" ,status );
}

/** ****************************************************************************
* @remarks       static void qxwz_software_timer_function(void *arg)
* @brief         QXWZ中断处理函数
* @param[in]     *arg 输入参数
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void qxwz_software_timer_function(void *arg)
{
    #define QXWZ_DATA_OUTPUT_CONTER   ( 3 )
    
    if( qxwz_data_active_st == DATA_ACTIVE_SUCC )
    {
        qxwz_timer_counter_reg++; 
        if( qxwz_timer_counter_reg >= QXWZ_DATA_OUTPUT_CONTER )
        {
            qxwz_timer_counter_reg = 0;
            qxwz_data_active_st = DATA_ACTIVE_INIT;
            if( qxwz_nmea_info_cb != NULL )
            {
                qxwz_nmea_info_cb( (uint8_t *)qxwz_data_recv_buf, qxwz_data_recv_len );
                memset( (uint8_t *)qxwz_data_recv_buf, 0x00, QXWZ_DATA_RECV_MAX_LEN );
                qxwz_data_recv_len = 0;
            }
       }
    }
}

/** ****************************************************************************
* @remarks       void qxwz_software_timer_start( void )
* @brief         启动定时器，周期性循环200ms秒钟
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static uint32_t qxwz_software_timer_start( void )
{
    #define QXWZ_SOFTWARE_TIMER   ( 200 )
    /*创建定时器功能，定时时间200ms*/
    qxwz_timer_handle = gaoz_timer_period_new( QXWZ_SOFTWARE_TIMER, qxwz_software_timer_function, NULL );
    if( qxwz_timer_handle == 0 )
    {
        return pdFAIL;
    }

    return pdPASS;
}

/** ****************************************************************************
* @remarks       void qxwz_software_timer_stop( void )
* @brief         停止定时器
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void qxwz_software_timer_stop( void )
{
    if( qxwz_timer_handle != 0 )
    {
        if( gaoz_timer_free( qxwz_timer_handle ) == 0 )
        {
            qxwz_timer_handle = 0;
        }
    }
}

/** ****************************************************************************
* @remarks       uint32_t qxwz_inject_para_init( void )
* @brief         千寻模块网络参数初始化
* @param[in]     fun 数据回调函数地址，*gpdrc_p GPDRC参数配置地址，*gpdrc4_p GPDRC4参数配置地址
* @param[out]    无
* @return        pdPASS 成功      pdFAIL
* @attention     GPDRC 服务器参数，GPDRC4 惯导数据
*******************************************************************************/
uint32_t qxwz_inject_para_init( qxwz_nmea_info_fun fun, uint8_t *gpdrc_p, uint8_t *gpdrc4_p )
{

	int ret = 0;
    int len = 0;
	QXWZSdkConfig *pcfg	= (QXWZSdkConfig *)&cfg;
	//QXWZSensorConfig config = { 0 };
    char *sdk_ver = NULL;

    ret = qxwz_inject_cfg_save_flash_read(&qxwz_save_cfg_infor);
    if(ret == pdFAIL)
    {
        OSI_PRINTFI("qxwz_inject_cfg_save_flash_read fail!\r\n");
        memset(&qxwz_save_cfg_infor,0,sizeof(qxwz_save_cfg_infor_t));
    }
    //if(( strlen((const char *)qxwz_save_cfg_infor.app_key) == 0 )
    //    || ( strlen((const char *)qxwz_save_cfg_infor.app_secret) == 0 )
    //        || ( strlen((const char *)qxwz_save_cfg_infor.device_type) == 0 )
    //            || ( strlen((const char *)qxwz_save_cfg_infor.device_id) == 0 ))
    //{
    //    log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"QXWZ network parameter is invalid\r\n" );
    //}
	pcfg->size = sizeof(QXWZSdkConfig);
	pcfg->log_enable = 1;
	pcfg->apply_scenario = 2;
#if QXWZ_SDK_TEST
    sprintf(pcfg->app_key,	   "%s", (const char *)APPKEY);
	sprintf(pcfg->app_secret,  "%s", (const char *)APPSECRET);
	sprintf(pcfg->device_type, "%s", (const char *)DEVICE_TYPE);
	sprintf(pcfg->device_id, "%s", (const char *)DEVICE_ID);
#else
    sprintf(pcfg->app_key,	   "%s", (const char *)qxwz_save_cfg_infor.app_key);
	sprintf(pcfg->app_secret,  "%s", (const char *)qxwz_save_cfg_infor.app_secret);
	sprintf(pcfg->device_type, "%s", (const char *)qxwz_save_cfg_infor.device_type);
	sprintf(pcfg->device_id, "%s", (const char *)qxwz_save_cfg_infor.device_id);
#endif  

	/* QXWZSdkCallbacks --------------------------------------------------*/
    if( sdk_hl == NULL )
    {
        memset(&cbs, 0, sizeof(QXWZSdkCallbacks));
        cbs.size			= sizeof(cbs);
        cbs.fill_raw_data	= fill_raw_data_cb;
        cbs.fill_nmea_info	= fill_nmea_info_cb;
        cbs.status_response = status_response_cb;
        sdk_hl = ( QXWZSdkInterface * )getQXWZSdkInterface();
        ret = sdk_hl->init(&cbs, pcfg);
        if( ret < 0 )
        {   /*屏蔽掉错误返回，系统只需要初始化一次，第二次就会返回错误*/
            return pdFAIL;
        }
    }
    sdk_ver = sdk_hl->get_ver_info();
    if( sdk_ver != NULL )
    {
        log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"SDK firmware version = %s\r\n", sdk_ver );
    }
	//memset(&config, 0, sizeof(config));
    //snprintf(config.acce_type, 64, "%s", "bmi055");
    //snprintf(config.gyro_type, 64, "%s", "bmi055");
    //snprintf(config.odom_type, 64, "%s", "G7odom");
    //ret = sdk_hl->inject_sensor_config(&config);
	//if( ret < 0 )
    //{
	//	return pdFAIL;
	//}
    if( gpdrc_p != NULL )
    {
        if( strnstr(( const char* )gpdrc_p , "GPDRC" , GPDRC_MAX_LEN ) != NULL )
        {
            len = strlen( (const char *)gpdrc_p );
            log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"Inject GPDRC data ,len = %d, data = %s\r\n", len, gpdrc_p );
            if( sdk_hl->ioctl( IOCTL_CMD_GPDRC_CFG, gpdrc_p, &len ) == 0 )
            {
                log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"GPDRC parameters set successfully\r\n" );
            } 
            else
            {
                log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"GPDRC parameters set error\r\n" );
            }
        }
    }
    if( gpdrc4_p != NULL )
    {
        if( strnstr(( const char* )gpdrc4_p , "GPDRC4" , GPDRC_MAX_LEN ) != NULL )
        {
            len = strlen( (const char *)gpdrc4_p );
            log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"Inject GPDRC4 data ,len = %d, data = %s\r\n", len, gpdrc4_p );
            if( sdk_hl->ioctl( IOCTL_CMD_GPDRC4_CFG, gpdrc4_p, &len ) == 0 )
            {
                log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"GPDRC4 parameters set successfully\r\n" );
            }
            else
            {
                log_debug_printf(INFOR_MODE , "QXWZ_SDK" ,"GPDRC4 parameters set error\r\n" );
            }
        }
    }
    if( fun != NULL )
    {
        qxwz_nmea_info_cb = fun;
    }
    
    return pdPASS;
}

/** ****************************************************************************
* @remarks       uint32_t qxwz_inject_sdk_start( void )
* @brief         启动 千寻模块数据接口
* @param[in]     无
* @param[out]    无
* @return        pdPASS 成功      pdFAIL
* @attention     无
*******************************************************************************/
uint32_t qxwz_inject_sdk_start( void )
{
    if( sdk_hl == NULL )
    {
        return pdFAIL;
    }
    if( sdk_hl->start() < 0)
    {  
        return pdFAIL;
    }
    if( qxwz_software_timer_start() != pdPASS )
    {
         return pdFAIL;
    }
    qxwz_data_active_st = DATA_ACTIVE_INIT;
    memset( (uint8_t *)qxwz_data_recv_buf, 0x00, QXWZ_DATA_RECV_MAX_LEN );
    qxwz_data_recv_len = 0;

    return pdPASS;
}

/** ****************************************************************************
* @remarks       uint32_t qxwz_inject_sdk_stop( void )
* @brief         停止 千寻模块数据接口
* @param[in]     无
* @param[out]    无
* @return        pdPASS 成功      pdFAIL
* @attention     无
*******************************************************************************/
uint32_t qxwz_inject_sdk_stop( void )
{
    if( sdk_hl == NULL )
    {
        return pdFAIL;
    }
    qxwz_software_timer_stop();
    if( sdk_hl->stop() < 0)
    {  
        return pdFAIL;
    }
    
    return pdPASS;
}

/** ****************************************************************************
* @remarks       void qxwz_inject_gnss_data( QXWZSdkInterface *psdk_hl, UINT8 *data, UINT16 len)
* @brief         千寻模块串口数据接口
* @param[in]     *psdk_hl  SDK参数指针
* @param[in]     *data 数据源地址
* @param[in]     len 数据长度
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
void qxwz_inject_gnss_data( QXWZSdkInterface *psdk_hl, UINT8 *data, UINT16 len)
{
	if(psdk_hl == NULL)
	{
		return;
	}
	psdk_hl->inject_gnss_data(data, len);
}

/** ****************************************************************************
* @remarks       void qxwz_inject_cfg_init( qxwz_save_cfg_infor_t *qwxz_cfg )
* @brief         初始化QXWZ 配置参数
* @param[in]     *qwxz_cfg 初始化数据
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
void qxwz_inject_cfg_init( qxwz_save_cfg_infor_t *qwxz_cfg )
{
    if( qwxz_cfg == NULL )
    {
        return;
    }
    memcpy((uint8_t *)&qxwz_save_cfg_infor, (const uint8_t *)qwxz_cfg, sizeof(qxwz_save_cfg_infor_t));
}

/** ****************************************************************************
* @remarks       uint32_t qxwz_inject_cfg_save_flash_write( qxwz_save_cfg_infor_t qwxz_cfg )
* @brief         保存QXWZ 配置参数到外部FLASH中
* @param[in]     *qwxz_cfg 保存数据源地址
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     无
*******************************************************************************/
uint32_t qxwz_inject_cfg_save_flash_write( qxwz_save_cfg_infor_t *qwxz_cfg )
{
    uint32_t ret = pdFAIL;
    sfb_buf_store_infor_s infor = { 0 };

    if( qwxz_cfg == NULL )
    {
        return pdFAIL;
    }
    infor.infor_len = sizeof(qxwz_save_cfg_infor_t);
    infor.infor_p = ( uint8_t * )qwxz_cfg;
    infor.infor_crc = CRC_INIT;
    ret = sfb_write_par_store( SF_QXWZ_CFG_DATA_ADDR , &infor );
    if( ret != 0 )
    {
        qxwz_inject_cfg_init( qwxz_cfg );
        ret = pdPASS;
    }
    
    return ret;
}

/** ****************************************************************************
* @remarks       uint32_t qxwz_inject_cfg_save_flash_read( qxwz_save_cfg_infor_t *qwxz_cfg )
* @brief         读取 QXWZ 配置参数
* @param[in]     无
* @param[out]    *qwxz_cfg 读取数据目标地址
* @return        pdPASS 成功 pdFAIL 失败
* @attention     无
*******************************************************************************/
uint32_t qxwz_inject_cfg_save_flash_read( qxwz_save_cfg_infor_t *qwxz_cfg )
{
    uint32_t ret = pdFAIL;
    sfb_buf_store_infor_s infor = { 0 };
    
    if( qwxz_cfg == NULL )
    {
        return pdFAIL;
    }
    infor.infor_len = sizeof(qxwz_save_cfg_infor_t);
    infor.infor_p = ( uint8_t * )qwxz_cfg;
    infor.infor_crc = CRC_INIT;
    if( sfb_read_par_store( SF_QXWZ_CFG_DATA_ADDR , &infor ) > 0 )
    {
        qxwz_inject_cfg_init( qwxz_cfg );
        ret = pdPASS;
    }
    
    return ret;
}

/** ****************************************************************************
* @remarks       uint32_t qxwz_inject_cfg_parameter_status_get( void )
* @brief         获取QXWZ 参数配置的状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 已配置 pdFAIL 无配置
* @attention     无
*******************************************************************************/
uint32_t qxwz_inject_cfg_parameter_status_get( void )
{
    if(( strlen((const char *)qxwz_save_cfg_infor.app_key) == 0 )
        || ( strlen((const char *)qxwz_save_cfg_infor.app_secret) == 0 )
            || ( strlen((const char *)qxwz_save_cfg_infor.device_type) == 0 )
                || ( strlen((const char *)qxwz_save_cfg_infor.device_id) == 0 ))
    {
        return pdFAIL;
    }
    
    return pdPASS;
}

/** ****************************************************************************
* @remarks       uint32_t qxwz_inject_sensor_data_set( float speed , uint64_t time )
* @brief         设置传感器数据
* @param[in]     speed 速度， time 时间
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     无
*******************************************************************************/
uint32_t qxwz_inject_sensor_data_set( float speed , uint64_t time )
{
    QXWZSensorData  sen_data = { 0 };

	if(sdk_hl == NULL)
    {
		return pdFAIL;
	}
    sen_data.m_Mask = QX_SENSOR_TYPE_ODOM;
    sen_data.m_Time = time;
    sen_data.m_Speed = speed;
	if( sdk_hl->inject_sensor_data( &sen_data ) < 0 )
    {
        return pdFAIL;
    }
    
    return pdPASS;
}

/** ****************************************************************************
* @remarks       uint32_t qxwz_inject_gpdrc_4_flash_write( qxwz_save_cfg_infor_t qwxz_cfg )
* @brief         保存GPDRC / GPDRC4 数据到外部FLASH
* @param[in]     *gpdrc *gpdrc4保存数据源地址
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     无
*******************************************************************************/
uint32_t qxwz_inject_gpdrc_4_flash_write( uint8_t *gpdrc, uint8_t *gpdrc4 )
{
    uint32_t ret = pdFAIL;
    sfb_buf_store_infor_s infor = { 0 };

    if(( gpdrc == NULL ) || ( gpdrc4 == NULL ))
    {
        return pdFAIL;
    }
    if( strnstr(( const char* )gpdrc , "GPDRC" , GPDRC_MAX_LEN ) != NULL )
    {
        infor.infor_len = GPDRC_MAX_LEN;
        infor.infor_p = ( uint8_t * )gpdrc;
        infor.infor_crc = CRC_INIT;
        if( sfb_write_par_store( SF_QXWZ_GPDRC_DATA_ADDR , &infor ) != 0 )
        {
            ret = pdPASS;
        }
    }
    if( ret == pdPASS )
    {
        ret = pdFAIL;
        if( strnstr(( const char* )gpdrc4 , "GPDRC4" , GPDRC_MAX_LEN ) != NULL )
        {
            infor.infor_len = GPDRC_MAX_LEN;
            infor.infor_p = ( uint8_t * )gpdrc4;
            infor.infor_crc = CRC_INIT;
            if( sfb_write_par_store( SF_QXWZ_GPDRC4_DATA_ADDR , &infor ) != 0 )
            {
                ret = pdPASS;
            }
        }
    }
    
    return ret;
}

/** ****************************************************************************
* @remarks       uint32_t qxwz_inject_gpdrc_4_flash_read( uint8_t *gpdrc, uint8_t *gpdrc4 )
* @brief         读取 GPDRC / GPDRC4 参数
* @param[in]     无
* @param[out]    *gpdrc / *gpdrc4 读取数据目标地址
* @return        pdPASS 成功 pdFAIL 失败
* @attention     无
*******************************************************************************/
uint32_t qxwz_inject_gpdrc_4_flash_read( uint8_t *gpdrc, uint8_t *gpdrc4 )
{
    uint32_t ret = pdFAIL;
    sfb_buf_store_infor_s infor = { 0 };
    
    if(( gpdrc == NULL ) || ( gpdrc4 == NULL ))
    {
        return pdFAIL;
    }
    infor.infor_len = GPDRC_MAX_LEN;
    infor.infor_p = ( uint8_t * )gpdrc;
    infor.infor_crc = CRC_INIT;
    if( sfb_read_par_store( SF_QXWZ_GPDRC_DATA_ADDR , &infor ) == 0 )
    {
        memset((uint8_t *)gpdrc, 0x00, GPDRC_MAX_LEN ); 
    }
    else
    {
        ret = pdPASS;
    }
    
    if( ret == pdPASS )
    {
        ret = pdFAIL;
        infor.infor_len = GPDRC_MAX_LEN;
        infor.infor_p = ( uint8_t * )gpdrc4;
        infor.infor_crc = CRC_INIT;
        if( sfb_read_par_store( SF_QXWZ_GPDRC4_DATA_ADDR , &infor ) == 0 )
        {
            memset((uint8_t *)gpdrc4, 0x00, GPDRC_MAX_LEN );
        }
        else
        {
            ret = pdPASS;
        }
    }
    
    return ret;
}

/** ****************************************************************************
* @remarks       void qxwz_inject_gpdrc_4_flash_clear( void )
* @brief         清空 GPDRC / GPDRC4 FLASH数据
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
void qxwz_inject_gpdrc_4_flash_clear( void )
{
    sfb_block_reset( SF_QXWZ_GPDRC_DATA_ADDR, SF_QXWZ_GPDRC_DATA_FlAG_SECTORS );
    sfb_block_reset( SF_QXWZ_GPDRC4_DATA_ADDR, SF_QXWZ_GPDRC4_DATA_FlAG_SECTORS );
}
